/*
 * Copyright Radosław Smogura, 2012. All rights reserved.
 *
 * The content of this file is confidential and it is intelectual property
 * of copyright owners.
 * 
 *
 * $URL: http://reprap-ide.googlecode.com/svn/trunk/RepRapIDE/RepRapProject/src/main/java/eu/softper/reprap/generator/SceneLine.java $
 * $Id: SceneLine.java 3 2012-11-19 10:58:30Z mail@smogura.eu $
 * $Revision: 3 $
 */
package eu.softper.reprap.generator;

import java.math.BigDecimal;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;

/**
 *
 * @author rsmogura
 */
public class SceneLine<T extends Number & Comparable<T>> {
    private DecimalVertex<T> v1;
    private DecimalVertex<T> v2;
    Boolean isV1MinYVertex;
    
    private SceneLineType lineType = SceneLineType.OUTLINE;
    
    private T minY, maxY;
    
    private T minX, maxX;
    
    private Set<T> xyNormalsAngles = new HashSet<T>();
    
    public SceneLine(DecimalVertex<T> v1, DecimalVertex<T> v2) {
        this.v1 = v1;
        this.v2 = v2;
    }

    public DecimalVertex<T> getV1() {
        return v1;
    }

    public void setV1(DecimalVertex<T> v1) {
        this.v1 = v1;
    }

    public DecimalVertex<T> getV2() {
        return v2;
    }

    public void setV2(DecimalVertex<T> v2) {
        this.v2 = v2;
    }

    public T getMinY() {
        if (minY == null) {
            if (getV1().getY().compareTo(getV2().getY()) < 0)
                minY = getV1().getY();
            else
                minY = getV2().getY();
                         
        }
        return minY;
    }
    
    public T getMaxY() {
        if (maxY == null) {
            if (getV1().getY().compareTo(getV2().getY()) < 0)
                maxY = getV2().getY();
            else
                maxY = getV1().getY();
        }
        return maxY;
    }
    
    public T getMinX() {
        if (minX == null){
            if (getV1().getX().compareTo(getV2().getX()) < 0)
                minX = getV1().getX();
            else
                minX = getV2().getX();
                         
        }
        return minX;
    }
    
    public T getMaxX() {
        if (maxX == null){
            if (getV1().getX().compareTo(getV2().getX()) < 0)
                maxX = getV2().getX();
            else
                maxX = getV1().getX();
        }
        return maxX;
    }

    /** Returns vertex representing minY */
    public DecimalVertex getMinYVertex() {
        if (isV1MinYVertex == null) {
            isV1MinYVertex = getMinY().compareTo(getV1().getY()) == 0;
        }
        
        if (isV1MinYVertex)
            return getV1();
        else
            return getV2();
    }
    
    /** Returns vertex representing maxY */
    public DecimalVertex getMaxYVertex() {
        if (isV1MinYVertex == null) {
            isV1MinYVertex = getMinY().compareTo(getV1().getY()) == 0;
        }
        
        if (isV1MinYVertex)
            return getV2();
        else
            return getV1();
    }
    
    public Set<T> getXyNormalsAngles() {
        return xyNormalsAngles;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final SceneLine other = (SceneLine) obj;
        if (hashCode() != other.hashCode())
            return false;
        
        if (this.v1 != other.v1 && this.v1 != other.v2 && (this.v1 == null || (!this.v1.equals(other.v1) && !this.v1.equals(other.v2)))) {
            return false;
        }
        
        if (this.v2 != other.v2 && this.v2 != other.v1 && (this.v2 == null || (!this.v2.equals(other.v1) && !this.v2.equals(other.v2)))) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = hash + (this.v1 != null ? this.v1.hashCode() : 0);
        hash = hash + (this.v2 != null ? this.v2.hashCode() : 0);
        return hash;
    }

    public SceneLineType getLineType() {
        return lineType;
    }

    @Override
    public String toString() {
        return "(" + v1 + "; " + v2 + ")";
    }

    public void setLineType(SceneLineType lineType) {
        this.lineType = lineType;
    }
    
    /** Compares lines by lowest y position. */
    public static class ByYComparator<T extends Number & Comparable<T>> implements Comparator<SceneLine<T>> {
        public static final ByYComparator SHARED_INSTANCE = new ByYComparator();

        @Override
        public int compare(SceneLine<T> o1, SceneLine<T> o2) {          
            return o1.getMinY().compareTo(o2.getMinY());
        }
        
    }
}
